package utility;

import java.util.Arrays;
import java.util.Random;

import core.genetic.Individual;

public class Utils
{
	public static Random random = new Random(17);
	
	
	public static int[] randomPermumation(int length) {
		int[] res = new int[length];
		for(int i = 0;i<length;i++)
			res[i] = i;
		
		for(int i = 1;i<length;i++)
		{			
			int j = random.nextInt(i);
			if (i!=j)
			{
				int pom = res[i];
				res[i] = res[j];
				res[j] = pom;
			}
		}		
		return res;
	}
	
	public static<T> void randomPermutation(T[] array) { 
		for(int i = 1;i<array.length;i++)
		{			
			int j = random.nextInt(i);
			if (i!=j)
			{
				T pom = array[i];
				array[i] = array[j];
				array[j] = pom;
			}
		}
		
	}
	
	/**
	 * Calculates cumulative probabilities of weighted costs, of given length
	 * 
	 * @return returns array with <code>length-1</code> elements - cumulative probability limits. 
	 */
	public static double[] calcCumulativeProb(Pair<Individual,Double>[] par, int length) {
		double[] prob = new double[length-1];

		double suma = 0;
		double min = Double.POSITIVE_INFINITY;
		for (int i=0; i<length; i++){
			suma += par[i].second();
			min = Math.min(min, par[i].second());
		}
		suma-=min*length;

		for(int i = 0;i<length-1;i++)
			if (i==0) 
				prob[i] = (par[i].second()-min)/suma;
			else prob[i] = prob[i-1]+(par[i].second()-min)/suma;
		return prob;
	}
	
	public static double[] calcCumulativeProb(double[] cost, int length) {
		double[] prob = new double[length-1];

		double suma = 0;
		double min = Double.POSITIVE_INFINITY;
		for (int i=0; i<length; i++){
			suma += cost[i];
			min = Math.min(min, cost[i]);
		}
		suma-=min*length;

		for(int i = 0;i<length-1;i++)
			if (i==0) 
				prob[i] = (cost[i]-min)/suma;
			else prob[i] = prob[i-1]+(cost[i]-min)/suma;
		return prob;
	}
	
	
	public static int randomW(double[] cumProb) {
		double r = random.nextDouble();
		int i = Arrays.binarySearch(cumProb, r);
		return i>=0?i:(-i-1);
	}
	
	
	
	//otezenjena verovatnoca
	public static int randomW(Pair<Individual,Double>[] par, int length){
		double suma = 0;
		double min = Double.POSITIVE_INFINITY;
		for (int i=0; i<length; i++){
			suma += par[i].second();
			min = Math.min(min, par[i].second());
		}
		suma-=min*length;
		double r = random.nextDouble()*suma;
		int p=0;
		while (suma>r){
			suma += -par[p].second()+min;
			p++;
		}
		return p-1;
	}
	
	//otezenjena verovatnoca
	public static int randomW(double[] tezina, int length){
		double suma = 0;
		double min = Double.POSITIVE_INFINITY;
		for (int i=0; i<length; i++){
			suma += tezina[i];
			min = Math.min(min, tezina[i]);
		}
		suma-=min*length;
		double r = random.nextDouble()*suma;
		int p=0;
		while (suma>r){
			suma += -tezina[p]+min;
			p++;
		}
		return p-1;
	}
	
	
	
	public static double sigmoid(double x) {
		return 1/(1+Math.exp(-10*x));		
	}
	
	
	public static double sqr(double a)
	{
		return a*a;
	}
}
